﻿using nblTool.utils;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using TouchSocket.Core;
using TouchSocket.Sockets;
using Communication;
using Jn698._45GWTool.Communication;
using Jn698._45GWTool.Models;
using CommonServiceLocator;
using WebFirst.Entities;
using GalaSoft.MvvmLight.Messaging;
using System.Windows.Threading;
using System.Collections.ObjectModel;
using System.Windows;
using Jn698._45GWTool.ViewModels;

namespace _698._45Tool.Utils
{
    internal class TcpHelper
    {
        private static TcpHelper instance = new TcpHelper();
        private Dictionary<string,GPRSInfo> GPRSDevices = new Dictionary<string,GPRSInfo>();
        public bool isComplete = false;

        /// <summary>
        /// 串口状态
        /// </summary>
        public ServerState Status => service.ServerState;

        /// <summary>
        /// 自定义串口消息接收事件
        /// </summary>
        public event EventHandler ReceiveDataEvent;
        private TcpHelper() 
        {
            
            service.Connecting = (client, e) => {
                Messenger.Default.Send<string>($"({DateTime.Now.ToString()})：有客户端正在连接", "Info");
                Console.WriteLine("有客户端正在连接");
                return EasyTask.CompletedTask;
            };//有客户端正在连接
            service.Connected = (client, e) => {
                Messenger.Default.Send<string>($"({DateTime.Now.ToString()})：客户端成功连接", "Info");
                Console.WriteLine("客户端成功连接");
                return EasyTask.CompletedTask;
            };//有客户端连接
            service.Disconnected = (client, e) => {
                foreach (var item in GPRSDevices.ToArray())
                {
                    if (item.Value.Id == client.Id)
                    {
                        GPRSDevices.Remove(item.Key);
                        Messenger.Default.Send<string>($"({DateTime.Now.ToString()})：客户端{item.Value.Address}断开连接", "Info");
                    }
                }
                System.Windows.Application.Current.Dispatcher.Invoke(() =>
                {
                    ObservableCollection<Device> devices = ServiceLocator.Current.GetInstance<MainViewModel>().DeviceList;
                    foreach (var item in devices.ToArray())
                    {
                        if (item.DeviceType.Equals("集中器"))
                        {
                            ServiceLocator.Current.GetInstance<MainViewModel>().DeviceList.Remove(item);
                        }
                    }
                    foreach (var item in GPRSDevices)
                    {
                        Device device = new Device() { DeviceType = "集中器", DeviceAddress = item.Value.Address };
                        ServiceLocator.Current.GetInstance<MainViewModel>().DeviceList.Add(device);
                    }
                });
                Console.WriteLine("客户端断开连接");
                return EasyTask.CompletedTask;
            };//有客户端断开连接
            service.Received = (client, e) =>
            {
                if (e.RequestInfo is MyUnfixedHeaderRequestInfo myRequestInfo)
                {
                    //此处可以处理MyUnfixedHeaderRequestInfo的相关信息了。
                    //string body = Encoding.UTF8.GetString(myRequestInfo.Body, 0, myRequestInfo.Body.Length);
                    ReceiveDataEventArg arg = new ReceiveDataEventArg();
                    //从服务器收到信息

                    //string mes = Encoding.UTF8.GetString(e.ByteBlock.Buffer, 0, e.ByteBlock.Len);
                    DateTime recvDateTime = DateTime.Now;
                    //arg.Data = Convert.to
                    string msgStr = "";
                    //arg.Data = System.Text.Encoding.UTF8.GetBytes(mes);
                    //var tempByte = ByteUtils.byteTrimEnd(e.ByteBlock.Buffer);
                    var tempByte = myRequestInfo.Body;
                    for (int i = 0; i < tempByte.Length; i++)
                    {
                        msgStr += tempByte[i].ToString("X2") + " ";
                    }
                    Console.WriteLine($"从{client.Id}接收到信息：{msgStr}");
                    arg.Data = AnalysisMessage.GetValidFrameByte(tempByte);
                    msgStr = "";
                    for (int i = 0; i < arg.Data?.Length; i++)
                    {
                        msgStr += arg.Data[i].ToString("X2") + " ";
                    }
                    //Messenger.Default.Send<string>($"接收帧({DateTime.Now.ToString()})：{msgStr}", "RecvMessage");
                    if (ReceiveDataEvent != null && arg.Data != null)
                    {

                        Enums.LinkEnum link = Enums.LinkEnum.Login;
                        GPRSInfo gPRSInfo = AnalysisMessage.AnalysisGPRSLogin(arg.Data, ref link);
                        if (gPRSInfo != null)
                        {

                            gPRSInfo.Id = client.Id;
                            switch (link)
                            {
                                case Enums.LinkEnum.Login:
                                    Messenger.Default.Send<string>($"接收帧({DateTime.Now.ToString()})：{msgStr}", "RecvMessage");
                                    if (GPRSDevices.ContainsKey(gPRSInfo.Address))
                                    {
                                        GPRSDevices.Remove(gPRSInfo.Address);
                                    }
                                    else
                                    {
                                        Device device = new Device { DeviceType = "集中器", DeviceAddress = gPRSInfo.Address };
                                        Application.Current.Dispatcher.Invoke(() =>
                                        {
                                            ServiceLocator.Current.GetInstance<MainViewModel>().DeviceList.Add(device);
                                        });
                                    }
                                    Messenger.Default.Send<string>($"({DateTime.Now.ToString()})：{gPRSInfo.Address}登录", "Info");
                                    GPRSDevices.Add(gPRSInfo.Address, gPRSInfo);
                                    var b = MessageGenerationModule.GetGPRSLinkResponseFrame(gPRSInfo, recvDateTime);
                                    msgStr = "";
                                    for (int i = 0; i < b.Length; i++)
                                    {
                                        msgStr += b[i].ToString("X2") + " ";
                                    }
                                    Messenger.Default.Send<string>($"发送上报应答帧({DateTime.Now.ToString()})：{msgStr}", "SendMessage");

                                    service.Send(client.Id, b);
                                    //service.Send(client.Id, MessageGenerationModule.GetGPRSLinkResponseFrame(gPRSInfo, recvDateTime));
                                    break;
                                case Enums.LinkEnum.Heart:
                                    Messenger.Default.Send<string>($"接收帧({DateTime.Now.ToString()})：{msgStr}", "RecvMessage");
                                    Messenger.Default.Send<string>($"({DateTime.Now.ToString()})：{gPRSInfo.Address}心跳", "Info");
                                    GPRSDevices[gPRSInfo.Address] = gPRSInfo;
                                    b = MessageGenerationModule.GetGPRSLinkResponseFrame(gPRSInfo, recvDateTime);
                                    msgStr = "";
                                    for (int i = 0; i < b.Length; i++)
                                    {
                                        msgStr += b[i].ToString("X2") + " ";
                                    }
                                    Messenger.Default.Send<string>($"发送上报应答帧({DateTime.Now.ToString()})：{msgStr}", "SendMessage");

                                    service.Send(client.Id, b);
                                    //service.Send(client.Id, MessageGenerationModule.GetGPRSLinkResponseFrame(gPRSInfo, recvDateTime));
                                    break;
                                case Enums.LinkEnum.Report:
                                    ReceiveDataEvent.Invoke(null, arg);
                                    b = MessageGenerationModule.GetREPORTResponseFrame(gPRSInfo);
                                    msgStr = "";
                                    for (int i = 0; i < b.Length; i++)
                                    {
                                        msgStr += b[i].ToString("X2") + " ";
                                    }
                                    Messenger.Default.Send<string>($"发送上报应答帧({DateTime.Now.ToString()})：{msgStr}", "SendMessage");

                                    service.Send(client.Id, b);
                                    break;
                                default:
                                    break;
                            }


                        }
                        else
                        {
                            ReceiveDataEvent.Invoke(null, arg);
                            isComplete = true;
                        }

                    }

                    
                }
                return EasyTask.CompletedTask;
            };
        }
        public static TcpHelper Instance { get { return instance; } }
        private TcpService service = new TcpService();

        public int Host;

       /* public TcpHelper()
        {
            if (service == null)
            {
                service = new TcpService();
                service.Connecting = (client, e) => {
                    Console.WriteLine("有客户端正在连接");
                    return EasyTask.CompletedTask; 
                };//有客户端正在连接
                service.Connected = (client, e) => {
                    Console.WriteLine("客户端成功连接");
                    return EasyTask.CompletedTask; 
                };//有客户端连接
                service.Disconnected = (client, e) => {
                    Console.WriteLine("客户端断开连接");
                    return EasyTask.CompletedTask; 
                };//有客户端断开连接
            }
        }*/
       public void SetTCP(int listenAddress)
        {
            //service.Received =
            Host = listenAddress;
        }
        
       
        public bool OpenTCP()
        {
            
            try
            {
                service.Setup(new TouchSocketConfig()
                //.SetListenIPHosts("tcp://127.0.0.1:7789", Host)//同时监听两个地址
                .SetListenIPHosts(new IPHost[] { new IPHost(Host) })
                //.SetTcpDataHandlingAdapter(() => new MyFixedHeaderCustomDataHandlingAdapter())
                .SetTcpDataHandlingAdapter(() => { return new MyCustomUnfixedHeaderDataHandlingAdapter(); })//配置适配器
                //.SetListenIPHosts(listenAddress)
                .ConfigureContainer(a =>
                {
                    a.AddConsoleLogger();
                })
                .ConfigurePlugins(a =>
                {
                    a.UseCheckClear()
                    .SetCheckClearType(CheckClearType.All)
                    .SetTick(TimeSpan.FromSeconds(600))
                    .SetOnClose((c, t) =>
                    {
                        c.TryShutdown();
                        c.SafeClose("超时无数据");
                    });
                }));
                /*service.AddListen(new TcpListenOption()
                {
                    IpHost= Host,
                });*/
                service.Start();
                return true;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
                return false;
            }
            

        }

        public void CloseTCP()
        {
            service?.Stop();
        }
        public void SendData(string address, byte[] b)
        {
            try
            {
                GPRSInfo gPRSInfo = GPRSDevices[address];
                service.Send(gPRSInfo.Id, b);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
        public override string ToString()
        {
            string msg = "";
            var host = Dns.GetHostEntry(Dns.GetHostName());
            foreach (var ip in host.AddressList)
            {
                if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                {
                    msg = ip.ToString();
                }
            }
            return msg;
        }
        public string GetIPAddress()
        {
            string ip = "0.0.0.0";
            try
            {
                WebClient MyWebClient = new WebClient();
                MyWebClient.Credentials = CredentialCache.DefaultCredentials;//获取或设置用于向Internet资源的请求进行身份验证的网络凭据

                Byte[] pageData = MyWebClient.DownloadData("http://www.net.cn/static/customercare/yourip.asp"); //从指定网站下载数据

                string pageHtml = Encoding.Default.GetString(pageData);  //如果获取网站页面采用的是GB2312，则使用这句

                int i1 = pageHtml.IndexOf("<h2>"), i2 = pageHtml.IndexOf("</h2>");
                ip = pageHtml.Substring(i1 + 1, i2 - 1 - i1);
                ip = ip.Substring(3, ip.Length - 3);
            }
            catch (WebException webEx)
            {
                webEx.Message.ToString();
            }
            return ip;
        }
        
    }
    #region 固定帧头适配器
    public class MyFixedHeaderRequestInfo : IFixedHeaderRequestInfo
    {
        /// <summary>
        /// 接口实现，标识数据长度
        /// </summary>
        public int BodyLength { get; private set; }

        /// <summary>
        /// 自定义属性，标识数据类型
        /// </summary>
        public byte DataType { get; set; }

        /// <summary>
        /// 自定义属性，标识指令类型
        /// </summary>
        public byte OrderType { get; set; }

        /// <summary>
        /// 自定义属性，标识实际数据
        /// </summary>
        public byte[] Body { get; set; }


        public bool OnParsingBody(byte[] body)
        {
            /*if (body.Length == this.BodyLength)
            {
                this.Body = body;
                return true;
            }
            return false;*/
            return true;
        }


        public bool OnParsingHeader(byte[] header)
        {
            //在该示例中，第一个字节表示后续的所有数据长度，但是header设置的是3，所以后续还应当接收length-2个长度。
            /*this.BodyLength = header[0] - 2;
            this.DataType = header[1];
            this.OrderType = header[2];*/
            return true;
        }
    }

    public class MyFixedHeaderCustomDataHandlingAdapter : CustomFixedHeaderDataHandlingAdapter<MyFixedHeaderRequestInfo>
    {
        /// <summary>
        /// 接口实现，指示固定包头长度
        /// </summary>
        public override int HeaderLength => 3;

        /// <summary>
        /// 获取新实例
        /// </summary>
        /// <returns></returns>
        protected override MyFixedHeaderRequestInfo GetInstance()
        {
            return new MyFixedHeaderRequestInfo();
        }
    }
    #endregion

    #region 不固定帧头适配器
    public class MyUnfixedHeaderRequestInfo : IUnfixedHeaderRequestInfo
    {
        public MyUnfixedHeaderRequestInfo(Action action)
        {
            this.m_actionForReset = action;
        }
        private readonly Action m_actionForReset;
        private int bodyLength;
        /// <summary>
        /// 接口实现，标识数据长度
        /// </summary>
        public int BodyLength
        {
            get { return bodyLength; }
        }


        private byte[] body;
        /// <summary>
        /// 自定义属性，标识实际数据
        /// </summary>
        public byte[] Body
        {
            get { return body; }
        }

        public int HeaderLength => throw new NotImplementedException();

        public bool OnParsingBody(byte[] body)
        {
            if (body.Length == this.bodyLength)
            {
                this.body = body;
                return true;
            }
            this.m_actionForReset.Invoke();
            return false;
        }


        public bool OnParsingHeader(ByteBlock byteBlock)
        {
            
            //从现有的可读数据中，读取“0x68”。
            
            int index = byteBlock.Buffer.IndexOfFirst(byteBlock.Pos, byteBlock.CanReadLen, new byte[] { 0x68 });
            if (index >= 0)
            {
                //索引到了“\r\n\r\n”，以此推断出，在当前缓存区中，由byteBlock.Pos至index的数据即为headers。
                int headerLength = index - byteBlock.Pos;
                //string headers = Encoding.UTF8.GetString(byteBlock.Buffer, byteBlock.Pos, headerLength);//解码headers
                byteBlock.Pos += headerLength;//然后将缓存区的游标移至headers结束的位置。

                //最后通过headers，解析出后续的body的长度，然后在此处赋值。
                this.bodyLength = BitConverter.ToInt16(new byte[] { byteBlock.Buffer[index+1], byteBlock.Buffer[index+2] }, 0)+2;//此处的0是占位值。
                if (bodyLength<5)
                {
                    this.m_actionForReset.Invoke();
                    return false;
                }
                return true;
            }
            else
            {
                //没索引到“68”，以此推断出，在当前缓存区中，header的接收尚未完成，
                //所以返回false，并且不需要修改游标。
                return false;
            }
        }
    }
    public class MyCustomUnfixedHeaderDataHandlingAdapter : CustomUnfixedHeaderDataHandlingAdapter<MyUnfixedHeaderRequestInfo>
    {
        public MyCustomUnfixedHeaderDataHandlingAdapter()
        {
            this.CacheTimeoutEnable = true;
            this.CacheTimeout = TimeSpan.FromSeconds(1);
            this.UpdateCacheTimeWhenRev = true;
        }
        protected override MyUnfixedHeaderRequestInfo GetInstance()
        {
            return new MyUnfixedHeaderRequestInfo(this.Reset);
        }
    }

    #endregion
}
